/*!
 * \file CsvHelper.h
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief CSV文件读写助手
 * \details 提供CSV文件的读取和解析功能，支持按列名和列索引访问数据
 */
#pragma once
#include <string.h>
#include <string>
#include <unordered_map>
#include <stdint.h>
#include <fstream>
#include <vector>
#include <sstream>

/*!
 * \brief CSV文件读取器
 * \details 用于读取和解析CSV格式文件，支持按列名和列索引访问数据
 */
class CsvReader
{
public:
	/*!
	 * \brief 构造函数
	 * \param item_splitter 字段分隔符，默认为逗号
	 */
	CsvReader(const char* item_splitter = ",");

public:
	/*!
	 * \brief 从文件加载CSV数据
	 * \param filename CSV文件路径
	 * \return 是否加载成功
	 */
	bool	load_from_file(const char* filename);

public:
	/*!
	 * \brief 获取列数
	 * \return 返回CSV文件的列数
	 */
	inline uint32_t	col_count() { return _fields_map.size(); }

	/*!
	 * \brief 获取指定列的32位整数
	 * \param col 列索引
	 * \return 32位整数值
	 */
	int32_t		get_int32(int32_t col);

	/*!
	 * \brief 获取指定列的无符号32位整数
	 * \param col 列索引
	 * \return 无符号32位整数值
	 */
	uint32_t	get_uint32(int32_t col);

	/*!
	 * \brief 获取指定列的64位整数
	 * \param col 列索引
	 * \return 64位整数值
	 */
	int64_t		get_int64(int32_t col);

	/*!
	 * \brief 获取指定列的无符号64位整数
	 * \param col 列索引
	 * \return 无符号64位整数值
	 */
	uint64_t	get_uint64(int32_t col);

	/*!
	 * \brief 获取指定列的双精度浮点数
	 * \param col 列索引
	 * \return 双精度浮点数值
	 */
	double		get_double(int32_t col);

	/*!
	 * \brief 获取指定列的字符串
	 * \param col 列索引
	 * \return 字符串值
	 */
	const char*	get_string(int32_t col);

	/*!
	 * \brief 获取指定列名的32位整数
	 * \param field 列名
	 * \return 32位整数值
	 */
	int32_t		get_int32(const char* field);

	/*!
	 * \brief 获取指定列名的无符号32位整数
	 * \param field 列名
	 * \return 无符号32位整数值
	 */
	uint32_t	get_uint32(const char* field);

	/*!
	 * \brief 获取指定列名的64位整数
	 * \param field 列名
	 * \return 64位整数值
	 */
	int64_t		get_int64(const char* field);

	/*!
	 * \brief 获取指定列名的无符号64位整数
	 * \param field 列名
	 * \return 无符号64位整数值
	 */
	uint64_t	get_uint64(const char* field);

	/*!
	 * \brief 获取指定列名的双精度浮点数
	 * \param field 列名
	 * \return 双精度浮点数值
	 */
	double		get_double(const char* field);

	/*!
	 * \brief 获取指定列名的字符串
	 * \param field 列名
	 * \return 字符串值
	 */
	const char*	get_string(const char* field);

	/*!
	 * \brief 移动到下一行
	 * \return 是否成功移动到下一行
	 */
	bool		next_row();

	/*!
	 * \brief 获取所有列名
	 * \return 以逗号分隔的列名字符串
	 */
	const char* fields() const 
	{ 
		static std::string s;
		if(s.empty())
		{
			std::stringstream ss;
			for (auto item : _fields_map)
				ss << item.first << ",";

			s = ss.str();
			s = s.substr(0, s.size() - 1);
		}

		return s.c_str();
	}

private:
	/*!
	 * \brief 检查单元格是否有效
	 * \param col 列索引
	 * \return 是否有效
	 */
	bool		check_cell(int32_t col);

	/*!
	 * \brief 根据列名获取列索引
	 * \param field 列名
	 * \return 列索引
	 */
	int32_t		get_col_by_filed(const char* field);

private:
	std::ifstream	_ifs;				///< 文件输入流
	char			_buffer[1024];		///< 行缓冲区
	std::string		_item_splitter;		///< 字段分隔符

	std::unordered_map<std::string, int32_t> _fields_map;	///< 列名到列索引的映射
	std::vector<std::string> _current_cells;				///< 当前行的单元格数据
};
